﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Text;
using Microsoft.DirectX;
using SimulationCore.Net.DTO;
using SimulationPresenter.Presentation.Primitives;
using SimulationPresenter.Simulation.Primitive;
using SimulationPresenter.Theater.Actors;
using SimulationPresenter.Presentation.Helpers;

namespace SimulationPresenter.Simulation.Helpers
{
    internal static class UpdateStateHelper
    {
        /// <summary>
        /// Updates primitive rotation with one gathered from Core
        /// </summary>
        /// <param name="primitive"></param>
        /// <param name="actorsState"></param>
        internal static void UpdateSimulationState(this ISimulationPrimitive primitive, ActorState selfState)
        {
            if (!(selfState is RidigActorState))
            {
                throw new InvalidOperationException(
                    string.Format("Actor state for Ridig body {0} is not a RidigActorState.", selfState.Name));
            }
            primitive.Transformation = (selfState as RidigActorState).Transformation;
        }

        internal static void UpdateClothState(this ICloth cloth, ActorState selfState, ref IPresentationPrimitive shape)
        {
            if (!(selfState is ClothState))
            {
                throw new InvalidOperationException(
                    string.Format("Actor state for Cloth body {0} is not a ClothState.", selfState.Name));
            }
            cloth.Grid.Vertexes = (selfState as ClothState).Vertices;
            shape.SetPositions(cloth.Grid.Vertexes);
        }

        /// <summary>
        /// Finds primitive in list of Actors' States 
        /// </summary>
        /// <param name="primitive"></param>
        /// <param name="actorsState"></param>
        /// <returns></returns>
        /// <exception cref="InvalidOperationException">When element was not found in simulation.</exception>
        internal static ActorState FindOwnState(this ISimulationPrimitive primitive, IList<ActorState> actorsState)
        {
            //Find own description in the list
            ActorState foundState;

            try
            {
                foundState = actorsState.First(x => x.Name == primitive.Name);
            }
            catch (InvalidOperationException)
            {
                throw new InvalidOperationException(string.Format("No actor state found for give primitive ({0}).", primitive.Name));
            }

            //if (null == foundState)
            //{
            //    throw new InvalidOperationException(string.Format("No actor state found for give primitive ({0}).", primitive.Name));
            //}

            if (primitive is MetalCloth)
            {
                if (!(foundState is ClothState))
                {
                    throw new DataException(
                        string.Format("Actor state found for MetalCloth ({0}) is not of type ClothState", primitive.Name));
                }
            } 
            else if (primitive is IRidig)
            {
                if (!(foundState is RidigActorState))
                {
                    throw new DataException(
                        string.Format("Actor state found for IRidig ({0}) is not of type RidigActorState", primitive.Name));
                }
            }

            return foundState;
        }

    }
}
